/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed under the Apache license, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.internna.iwebjtracker.model;

import java.util.Date;
import java.util.Locale;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.directwebremoting.annotations.DataTransferObject;
import org.directwebremoting.annotations.RemoteProperty;
import org.hibernate.validator.NotNull;
import org.internna.iwebjtracker.activity.model.RecordedActivity;
import org.internna.iwebmvc.metadata.ui.EntityFilter;
import org.internna.iwebmvc.metadata.ui.GridColumn;
import org.internna.iwebmvc.model.AbstractOwnedDomainEntity;
import org.internna.iwebmvc.model.Rating;
import org.springframework.core.style.ToStringCreator;

/**
 * Records important operations on other entities.
 *
 * @author Jose Noheda
 * @since 1.0
 */
@Entity
@Table(name = "ACTIVITY")
@NamedQuery(name = "Activity.findAll", query = "SELECT a FROM Activity a")
@DataTransferObject(javascript = "Activity")
public class Activity extends AbstractOwnedDomainEntity implements RecordedActivity {

    private static final long serialVersionUID = -1573614325691841307L;

    /**
     * Fills default values for event date and priority.
     */
    public Activity() {
        eventDate = new Date();
        activityPriority = new Rating();
    }

    @NotNull
    @RemoteProperty
    @GridColumn(order = 2)
    @Column(name = "ACTIVITY_TYPE")
    @EntityFilter(type = EntityFilter.WIDGET_TYPE.ENUM)
    private ActivityType type;

    @NotNull
    @RemoteProperty
    @GridColumn(order = 3)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "EVENT_DATE")
    @EntityFilter(order = 1, type = EntityFilter.WIDGET_TYPE.DATE, range = true)
    private Date eventDate;

    @NotNull
    @RemoteProperty
    @GridColumn (order = 5, relativeWidth = 2D)
    @JoinColumn(name = "PROJECT", nullable = false)
    @EntityFilter(order = 3, type = EntityFilter.WIDGET_TYPE.ENTITY)
    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
    private DefaultProject project;

    @ManyToOne
    @RemoteProperty
    @GridColumn (order = 6)
    @JoinColumn(name = "ISSUE")
    @EntityFilter(order = 4, type = EntityFilter.WIDGET_TYPE.ENTITY)
    private DefaultIssue issue;

    @Embedded
    @GridColumn
    @RemoteProperty
    @EntityFilter(order = 5, type = EntityFilter.WIDGET_TYPE.RATING, range = true)
    private Rating activityPriority;

    @RemoteProperty
    @GridColumn (order = 4)
    @JoinColumn(name = "ORIGINATOR")
    @EntityFilter(order = 2, type = EntityFilter.WIDGET_TYPE.ENTITY)
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private TrackerUser originator;

    /**
     * Accessor method
     */
    public Date getEventDate() {
        return eventDate;
    }

    /**
     * Accessor method
     */
    protected void setEventDate(Date eventDate) {
        this.eventDate = eventDate;
    }

    /**
     * Accessor method
     */
    public ActivityType getType() {
        return type;
    }

    /**
     * Accessor method
     */
    public void setType(ActivityType type) {
        this.type = type;
        if (type != null) {
            getActivityPriority().setRating(getType().getPriority());
        }
    }

    /**
     * Accessor method
     */
    public DefaultProject getProject() {
        return project;
    }

    /**
     * Accessor method
     */
    public void setProject(DefaultProject project) {
        this.project = project;
    }

    /**
     * Accessor method
     */
    public Rating getActivityPriority() {
        return activityPriority;
    }

    /**
     * Accessor method
     */
    protected void setActivityPriority(Rating activityPriority) {
        this.activityPriority = activityPriority;
    }

    /**
     * Accessor method
     */
    public DefaultIssue getIssue() {
        return issue;
    }

    /**
     * Adds an issue as long as it's null or has a project that matches the one already configured.
     *
     * @param issue any
     */
    public void setIssue(DefaultIssue issue) {
        if ((issue == null) || ((issue.getParentProject() != null) && (issue.getParentProject().equals(this.project)))) {
            this.issue = issue;
        } else if ((issue.getParentProject() != null) && (this.project == null)) {
            this.issue = issue;
            this.project = issue.getParentProject();
        }
    }

    /**
     * Accessor method
     */
    public TrackerUser getOriginator() {
        return originator;
    }

    /**
     * Accessor method
     */
    public void setOriginator(TrackerUser originator) {
        this.originator = originator;
    }

    /**
     * Show activity type in widgets.
     *
     * @param locale any
     * @return an empty string unless type has value
     */
    @Override public final String getCaption(Locale locale) {
        return type == null ? "" : type.toString();
    }

    /**
     * For logging purposes mainly.
     *
     * @return strign built using Spring styling
     */
    @Override public String toString() {
        ToStringCreator creator = new ToStringCreator(this);
        creator.append("type", type);
        return creator.toString();
    }

}
